package main

import (
	"log"
	"net"
	"os"
	"os/signal"
	"sync"
	"syscall"
)

func makeReply(msg []byte) []byte {
	replyPrefix := []byte("You said: ")
	return append(replyPrefix, msg...)
}

type MyTcpServerHandler struct{}

func (h MyTcpServerHandler) OnRecv(conn net.Conn, msg []byte) {
	log.Printf("Received from %v: %s", conn.RemoteAddr(), string(msg))

	replyContent := makeReply(msg)

	conn.Write(replyContent)
	log.Printf("Reply to %v: %s", conn.RemoteAddr(), string(replyContent))
}

type MyUdpServerHandler struct{}

func (h MyUdpServerHandler) OnRecv(conn *net.UDPConn, remoteAddr *net.UDPAddr, msg []byte) {
	log.Printf("Received from %v: %s", remoteAddr, string(msg))

	replyContent := makeReply(msg)

	conn.WriteToUDP(replyContent, remoteAddr)
	log.Printf("Reply to %v: %s", remoteAddr, string(replyContent))
}

func main() {
	log.Println("main()")

	c := make(chan os.Signal, 1)
	var signalWg sync.WaitGroup

	signal.Notify(c, os.Interrupt, syscall.SIGTERM)
	signal.Notify(c, os.Interrupt, syscall.SIGINT)

	signalWg.Add(1)

	go func() {
		<-c
		log.Println("Exiting now")
		signalWg.Done()
	}()

	tcpServer := NewTcpServer(":60000", MyTcpServerHandler{})
	udpServer := NewUdpServer(":60000", MyUdpServerHandler{})

	log.Printf("Server is listening on %s, %s\n", tcpServer.Network(), tcpServer.Addr())
	log.Printf("Server is listening on %s, %s\n", udpServer.Network(), udpServer.Addr())

	signalWg.Wait()

	tcpServer.Stop()
	udpServer.Stop()

	log.Println("Exited")
}
